home *** CD-ROM | disk | FTP | other *** search
- /*
- * ntcp.c
- *
- * Copyright (C) 1995 Martin von L÷wis
- * Copyright (C) 1997 RΘgis Duchesne
- */
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
-
- #include <stdio.h>
- #include <errno.h>
- #ifdef HAVE_FCNTL_H
- #include <fcntl.h>
- #endif
- #ifdef HAVE_GETOPT_H
- #include <getopt.h>
- #else
- #define getopt_long(a,v,o,ol,x) getopt(a,v,o)
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_IO_H
- #include <io.h>
- #endif
- #include <string.h>
- #include <stdlib.h>
- #include <limits.h>
- #include "ntfstypes.h"
- #include "struct.h"
- #include "util.h"
- #include "nttools.h"
- #include "inode.h"
-
- char *short_opts="Vh";
- #ifdef HAVE_GETOPT_H
- struct option options[]={
- {"version",0,0,'V'},
- {"help",0,0,'h'},
- {0,0,0,0}
- };
- #endif
-
- unsigned int type=ngt_nt;
- unsigned int charset=nct_utf8;
-
-
- void usage(void)
- {
- fprintf(stderr,"ntcp [-V|h] <src> <dst>\n"
- "Files on the NTFS volume are accessed as //<device>/<path>\n");
- }
-
- struct ntfs_file{
- ntfs_inode ino;
- ntfs_attribute *data;
- ntfs_offset_t offset;
- };
-
- void
- write_unix(void *file,void *buf,size_t len)
- {
- if(write(*(int*)file,buf,len)!=len){
- perror("cp2unix");
- exit(1);
- }
- }
-
- int
- read_unix(void *file,void *buf,size_t len)
- {
- int result;
- result=read(*(int*)file,buf,len);
- if(result==-1){
- perror("read_unix");
- exit(1);
- }
- return result;
- }
-
- int
- close_unix(void *file)
- { /* When close is Ok, errno isn't set to zero in some implementation */
- if(close(*(int*)file)==0)
- return 0;
- else
- return errno;
- }
-
- void
- write_nt(void *file,void* buf,size_t len)
- {
- struct ntfs_file* f=file;
- struct ntfs_io io;
- int error;
- io.fn_get=ntfs_get;
- io.param=buf;
- io.size=len;
- io.do_read=0;
- error=ntfs_readwrite_attr(&f->ino,f->data,f->offset,&io);
- if(error){
- fprintf(stderr,"Error %d writing to ntfs\n",error);
- exit(1);
- }
- f->offset+=len;
- }
-
- int
- read_nt(void *file,void *buf,size_t len)
- {
- struct ntfs_file* f=file;
- struct ntfs_io io;
- int error;
- io.fn_put=ntfs_put;
- io.param=buf;
- io.size=len;
- io.do_read=1;
- error=ntfs_readwrite_attr(&f->ino,f->data,f->offset,&io);
- if(error){
- fprintf(stderr,"Error %d reading from ntfs\n",error);
- exit(1);
- }
- f->offset+=io.size;
- return io.size;
- }
-
- int
- close_nt(void *file)
- {
- return ntfs_update_inode(file);
- }
-
- typedef struct _methods
- {
- void (*write_func)(void*,void*,size_t);
- int (*read_func)(void*,void*,size_t);
- int (*close_func)(void*);
- } *methods;
-
- struct _methods m_unix =
- {
- write_unix,
- read_unix,
- close_unix
- };
-
- struct _methods m_nt =
- {
- write_nt,
- read_nt,
- close_nt
- };
-
- void copy(methods r,void *rf,methods w,void *wf)
- {
- void *buf=malloc(8192);
- int len;
- int error;
-
- do{
- len=r->read_func(rf,buf,8192);
- w->write_func(wf,buf,len);
- }while(len==8192);
- error = w->close_func(wf);
- if(error)
- fprintf(stderr,"When closing w:%s\n", strerror(error));
- error = r->close_func(rf);
- if(error)
- fprintf(stderr,"When closing r:%s\n", strerror(error));
- }
-
- int
- ntfs_creat (ntfs_inode *dir, ntfs_inode *ino, char* name)
- {
- int error;
-
- error=ntfs_alloc_file(dir,ino,name,strlen(name));
- if(error)
- return error;
- error=ntfs_update_inode(ino);
- if(error)
- return error;
- error=ntfs_update_inode(dir);
- return error;
- }
-
- int
- ntfs_open(char *name,methods m,void **f,int flags)
- {
- ntfs_volume *vol;
- char device[256];
- char *it;
- int inum;
- struct ntfs_file *file;
- int error;
-
- for(it=name+2;*it && *it!='/';it++)
- /*nothing*/;
- if(it!=name+2)
- {
- strcpy(device,"/dev/");
- strncpy(device+5,name+2,(it-name)-2);
- device[(it-name)+3]='\0';
- }
- vol=ntfs_open_volume(device,0,1,0);
- if(!vol)return ENODEV;
- vol->ngt=type;
- vol->nct=charset;
-
- file=malloc(sizeof(struct ntfs_file));
- inum=5;
- /* walk the directory tree */
- name=it;
- if(*name=='/')name++;
- do{
- char *next;
- if(ntfs_init_inode(&file->ino,vol,inum)){
- fprintf(stderr,"error finding %s\n",it);
- return EIO;
- }
- if(!name || !*name)break;
- next=strpbrk(name,NTFS_PATH_SEP);
- if(next){
- *next='\0';
- next++;
- }
- inum=ntfs_find_file(&file->ino,name);
- if(inum==-1){
- ntfs_inode new_ino;
- if(next)
- return ENOENT;
- error = ntfs_creat(&file->ino, &new_ino, name);
- if(error)
- return error;
- file->ino = new_ino;
- break;
- }
- name=next;
- }while(1);
- file->data=ntfs_find_attr(&file->ino,vol->at_data,0);
- if(!file->data)
- return EISDIR;
- *m = m_nt;
- *f = file;
- return 0;
- }
-
- int
- unix_open(char *name,methods m,void **f,int flags)
- {
- int *file=malloc(sizeof(int));
- *file=open(name,flags,0777);
- if(*file==-1)return errno;
- *m = m_unix;
- *f=file;
- return 0;
- }
-
- int
- do_open(char *name,methods m,void **f,int flags)
- {
- int error;
- if(name[0]=='/' && name[1]=='/')
- error=ntfs_open(name,m,f,flags);
- else
- error=unix_open(name,m,f,flags);
-
- if(error == EISDIR && (flags & O_CREAT))
- return error;
-
- if(error){
- fprintf(stderr,"%s:%s\n",name,strerror(error));
- exit(1);
- }
- return 0;
- }
-
- void
- join(char* dir, char* file)
- {
- char *next;
- for(next = strpbrk(dir,NTFS_PATH_SEP);next;
- next = strpbrk(next,NTFS_PATH_SEP))
- dir=next=next+1;
- if(*dir != '\0')
- {
- dir += strlen(dir);
- *dir = '/';
- dir++;
- }
- for(next = strpbrk(file, NTFS_PATH_SEP); next;
- next = strpbrk(next, NTFS_PATH_SEP))
- file = next = next+1;
- strcpy(dir,file);
- }
-
- int main(int argc,char *argv[])
- {
- int c;
- extern int opterr,optind;
- extern char* optarg;
- struct _methods m1,m2;
- void *f1,*f2;
-
- opterr=1;
- while((c=getopt_long(argc,argv,short_opts,options,NULL))>0)
- switch(c)
- {
- case 'V': printf("ntcp" NTFS_VERSION "\n");exit(0);break;
- case 'h': usage();exit(0);break;
- }
- if(optind+2!=argc){
- usage();
- exit(1);
- }
- #ifdef MSDOS
- do_open(argv[optind], &m1, &f1, O_RDONLY|O_BINARY);
- if(do_open(argv[optind+1], &m2, &f2, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY) == EISDIR)
- #else
- do_open(argv[optind], &m1, &f1, O_RDONLY);
- if(do_open(argv[optind+1], &m2, &f2, O_WRONLY|O_CREAT) == EISDIR)
- #endif
- {
- char newname[NAME_MAX];
- strcpy(newname, argv[optind+1]);
- join(newname,argv[optind]);
- #ifdef MSDOS
- if(do_open(newname, &m2, &f2, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY) == EISDIR)
- #else
- if(do_open(newname, &m2, &f2, O_WRONLY|O_CREAT) == EISDIR)
- #endif
- {
- fprintf(stderr,"%s:%s\n",newname,strerror(EISDIR));
- exit(1);
- }
- }
- copy(&m1,f1,&m2,f2);
- return 0;
- }
-
- /*
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
-